<template>
	<div
		:class="[
			'app-editor-container',
			'app-custom-dropdown-list',
			`app-custom-dropdown-list-${name}`,
		]"
	>
		<a-tree-select
			:value="curValue"
			:placeholder="placeholder"
			:tree-data="items"
			:disabled="disabled || readonly"
			:tree-checkable="multiple"
			:fieldNames="fieldNames"
			clearable
			:allowClear="true"
			@blur="onBlur"
			@focus="onFocus"
			@change="onChange"
		>
		</a-tree-select>
	</div>
</template>
<script lang="ts" setup>
import { computedNavData, deepCopy, IEvent, IParam, typeOf } from '@/core';
import { Http } from '@/http';
import { Ref } from 'vue';
import { customDropdownListProps } from './custom-dropdown-list';
import { useEditorTypeParams } from '@/hooks/use-editor';
interface EditorEmit {
	(name: 'component-action', value: IEvent<string>): void;
}
const props = defineProps(customDropdownListProps);
const emit = defineEmits<EditorEmit>();
// 类型校验
const {
	validateConfig,
	valueType,
	valueSeparator,
	objectNameField,
	objectIdField,
	objectValueField,
} = useEditorTypeParams();
validateConfig();

const items: Ref<IParam[]> = ref([]);

const fieldNames = computed(() => {
	const tempData = { label: 'label', value: 'value', options: 'children' };
	Object.assign(tempData, props.fieldMap);
	return tempData;
});

let curUrl: string = '';

let data: IParam[] = [];

watch(
	() => props.data,
	(newVal: any, oldVal: any) => {
		load();
	}
);

/**
 * 计算值
 */
const curValue = computed(() => {
	let value: any;
	let item: any = deepCopy(props.value as any);
	try {
		if (item) {
			if (props.multiple) {
				value = [];
				if (valueType == 'SIMPLES') {
					value = item;
				} else if (valueType == 'OBJECTS') {
					item.forEach((_item: any) => {
						value.push(_item[objectIdField as string]);
					});
				} else {
					value =
						item.split(
							valueSeparator ? valueSeparator : props.valueSeparator
						) || [];
				}
			} else {
				if (item && valueType == 'OBJECT') {
					value = item[objectIdField as string];
				} else {
					value = item;
				}
			}
		}
	} catch (error) {
		console.log(error);
	}
	return value;
});

/**
 * 加载树数据
 */
const load = () => {
	const tempUrl = computeUrl();
	if (tempUrl && tempUrl != curUrl) {
		curUrl = tempUrl;
		data = [];
		const _data = computedNavData(
			props.data,
			props.context,
			props.viewParams,
			props.filterParams
		);
		Http.getHttp()
			[props.method](tempUrl, _data)
			.then((response: any) => {
				if (!response || !response.success) {
					App.getNotificationHelper().error(
						App.ts('common.generic.error', '错误'),
						App.ts('common.customdropdownlist.loadfail', '数据加载失败')
					);
					return;
				}
				if (response.data && response.data.length > 0) {
					data = [...response.data];
					handleItems(response.data);
				}
			})
			.catch((error: any) => {
				App.getNotificationHelper().error(
					App.ts('common.generic.error', '错误'),
					App.ts('common.customdropdownlist.loadfail', '数据加载失败')
				);
			});
	} else {
		App.getNotificationHelper().error(
			App.ts('common.generic.error', '错误'),
			App.ts('common.customdropdownlist.nourl', '无数据加载路径')
		);
	}
};

/**
 * 计算数据请求路径
 */
const computeUrl = () => {
	let url = props.url;
	const tempMap = props.urlMap ? Object.keys(props.urlMap) : [];
	if (url && tempMap && tempMap.length > 0) {
		tempMap.forEach((item: string) => {
			const tempValue = props.urlMap[item];
			let targetValue = null;
			if (props.data.hasOwnProperty(tempValue)) {
				targetValue = props.data[tempValue];
			} else if (props.context.hasOwnProperty(tempValue)) {
				targetValue = props.context[tempValue];
			} else if (props.viewParams.hasOwnProperty(tempValue)) {
				targetValue = props.viewParams[tempValue];
			}
			const str = '${' + item + '}';
			url = url.replaceAll(str, targetValue);
		});
	}
	return url;
};

/**
 * 构建树形数据结构
 */
const handleItems = (data: IParam[]) => {
	if (props.fieldMap) {
		const parentId = props.fieldMap['pid'];
		if (parentId) {
			const valueName: string = props.fieldMap['value']
				? props.fieldMap['value']
				: 'value';
			items.value = handleChildren(data, parentId, valueName);
			return;
		}
	}
	items.value = data;
};

/**
 * 处理父子层级
 */
const handleChildren = (data: IParam[], parentId: string, curValue: string) => {
	let tempData: any[] = [];
	const setChildItems = (
		pValue: string,
		result: Array<IParam>,
		curItem: IParam
	) => {
		result.forEach((item: IParam) => {
			if (item[parentId] == pValue) {
				let valueField: string = item[curValue];
				setChildItems(valueField, result, item);
				if (!curItem.children) {
					curItem.children = [];
				}
				curItem.children.push(item);
			}
		});
	};
	data.forEach((curItem: IParam) => {
		if (!curItem[parentId]) {
			let valueField: string = curItem[curValue];
			setChildItems(valueField, data, curItem);
			tempData.push(curItem);
		}
	});
	return tempData;
};

/**
 * 值改变
 */
const onChange = (select: any, option: any) => {
	const value = handleSelectData(select);
	emit('component-action', {
		name: props.name as string,
		action: 'valueChange',
		data: value,
	});
};
/**
 * @description 处理处理选中数据
 * @param select 选中数据
 */
const handleSelectData = (select: any): any => {
	let result: any;
	const valueName: string = props.fieldMap['value']
		? props.fieldMap['value']
		: 'value';
	if (typeOf(select) == 'array') {
		if (valueType == 'SIMPLES') {
			result = select;
		} else if (valueType == 'OBJECTS') {
			result = [];
			select.forEach((_select: string) => {
				const item = data.find((item: any) => item[valueName] == _select);
				if (item) {
					result.push(handleObjectParams(item));
				}
			});
		} else {
			result = select.join(
				valueSeparator ? valueSeparator : props.valueSeparator
			);
		}
		result = result.length > 0 ? result : null;
	} else {
		if (valueType == 'OBJECT') {
			const item = data.find((item: any) => item[valueName] == select);
			if (item) {
				result = handleObjectParams(item);
			}
		} else {
			result = select;
		}
		result = result ? result : null;
	}
	return result;
};
/**
 * @description 处理对象类型参数
 * @param select 选中数据
 */
const handleObjectParams = (select: IParam): IParam => {
	const object: IParam = {};
	const valueName: string = props.fieldMap['value']
		? props.fieldMap['value']
		: 'value';
	const labelName: string = props.fieldMap['label']
		? props.fieldMap['label']
		: 'label';
	if (objectNameField) {
		Object.assign(object, {
			[objectNameField]: select[labelName],
		});
	}
	if (objectIdField) {
		Object.assign(object, {
			[objectIdField]: select[valueName],
		});
	}
	if (objectValueField) {
		Object.assign(object, {
			[objectValueField]: deepCopy(select),
		});
	}
	return object;
};
/**
 * 失去焦点
 */
const onBlur = () => {
	emit('component-action', {
		name: props.name as string,
		action: 'editorBlur',
		data: props.value,
	});
};

/**
 * 获取焦点
 */
const onFocus = () => {
	//重新加载数据并抛出聚焦事件
	emit('component-action', {
		name: props.name as string,
		action: 'editorFocus',
		data: props.value,
	});
};
</script>
